
function SOMNode(id, readTime, vizualizations, prefered)
{
	this.id = id;
	this.d = prefered + this.readTimeC * Math.log(1 + readTime) + Math.log(1 + vizualizations); 
}

SOMNode.prototype.readTimeC = 0;

function SOM(numOfNodes, dbHandler) {
	this.nodes = new Array();
	this.learnRate = 0.5;
	this.distanceThreshold = this.singleIncreaseValue - 1;
	this.databaseHandler = dbHandler;
}

SOM.prototype.addNode = som_add_node;
SOM.prototype.randomWeights = som_random_weights;
SOM.prototype.getBestNode = som_get_best_node;
SOM.prototype.updateSOM = som_update;
SOM.prototype.getNodeById = som_get_node_by_id;
SOM.prototype.updateCategory = som_updateCategory;

SOM.prototype.minUpdateDistance = 1;
SOM.prototype.singleIncreaseValue = 1.12;

function som_add_node(node) {
	this.nodes.push(node);
}

function som_random_weights(count) 
{
	//initialize the random weigths
	var vect = new Array(count);
	
	for (i=0; i<count; i++)
	{
		vect[i] = Math.random();
	}
	
	return vect;
}

function som_get_best_node(node)
{
	var closest;
	var min_d=99999; //large initial value
	
	for (i=0; i < this.nodes.length; i++)
	{
		distance = Math.abs(node.d - this.nodes[i].d);
		
		if (distance!=0) //make sure we don't use the distance from the point to itself
		{
			if (distance < min_d)
			{
				min_d = distance;
				closest = i;
			}
		}
	}
	
	return closest; //return index of closest node
}

function som_update(node) //update nodes close to this node
{
	do
	{
		flag = false;
		for (i = 0; i < this.nodes.length; i++)
		{
			if (Math.abs(node.d - this.nodes[i].d) < this.minUpdateDistance)
			{
				this.nodes[i].d = this.nodes[i].d + this.learnRate * (node.d - this.nodes[i].d);
				
				if (Math.abs(this.nodes[i].d - node.d) > this.distanceThreshold)
					flag = true;
			}
		}
	}
	while (flag);
}

function som_updateCategory(id) {
	node = this.getNodeById(id);
	this.databaseHandler.updateCategory(id, node.d * this.singleIncreaseValue, 0, 1);
}

function som_get_node_by_id(id) {
	for(i = 0; i < this.nodes.length;i++) {
		if(this.nodes[i].id == id) {
			return this.nodes[i];
		}
	}
	return null;
}